package com.lingxu.base.system.manage.util;

import org.apache.commons.lang.StringUtils;

/**
 * 父子编码生成规则(按默认规则递增，数字从1-999开始递增，数字到999，递增字母;位数不够请增加位数)
 *
 * 同级：A001->A002
 * 父子级: A001->A001A001
 * 有一个“单位编码中数字位数”的全局变量
 * 有两个关键方法
 * “获取同级下一个编码”
 * ”获取子级下一个编码“
 */
public class FatherSonCodeUtil {

    // 数字位数(默认生成3位的数字)
    private static final int numLength = 3;//代表数字位数

    /**
     * 根据当前code，获取同级下一个code
     * 例如:当前code为A001A002A003A004，下一个code将为：A001A002A003A005
     *
     * @param code 当前code
     * @return 同级下一个code
     */
    public static synchronized String getSameLevelNextCode(String code) {
        String result = "";
        if (StringUtils.isBlank(code)) {
            String letter = "A";
            String num = getStrNum(1);
            result = letter + num;
        } else {
            //substring为左闭右开
            //此时beforeCode=A001A002A003 afterCode=A004
            String beforeCode = code.substring(0, code.length() - 1- numLength);
            String afterCode = code.substring(code.length() - 1 - numLength);

            //afterCodeLetter为A
            //afterCodeNum 为4
            char afterCodeLetter = afterCode.substring(0, 1).charAt(0);
            int afterCodeNum = Integer.parseInt(afterCode.substring(1));

            String nextNum;
            char nextLetter;
            // 先判断数字等于999，则计数从1重新开始，则字母从A重新开始，递增
            if (afterCodeNum == getMaxNum()) {
                nextNum = getNextStrNum(0);
                nextLetter = getNextLetter(afterCodeLetter);
            } else {
                nextNum = getNextStrNum(afterCodeNum);
                nextLetter = afterCodeLetter;
            }

            // 如果是Z999，则下一个code就是Z999A001
            if ('Z' == afterCodeLetter && getMaxNum() == afterCodeNum) {
                //此时 nextLetter和nextNum必然经过计算成为了A 和 001
                result = code + (nextLetter + nextNum);
            } else {
                result = beforeCode + (nextLetter + nextNum);
            }
        }
        return result;

    }



    /**
     * 根据父亲code以及当前结点,获取下级的下一个code
     *
     * 例如：父亲code:A01
     *      当前code:A01B03 或null
     *      获取的code:A01B04 或A01A01
     *
     * @param parentCode   上级code
     * @param nowCode    同级code
     * @return 同级code的下一个code
     */
    public static synchronized String getSubLevelNextCode(String parentCode,String nowCode) {
        //如果nowCode存在 则用nowCode返回同级code
        //如果nowCode不存在 则用parentCode 返回子级code

        if(StringUtils.isNotBlank(nowCode)){
            //如果nowCode非空 则根据该nowCode获取同级Code。
            return getSameLevelNextCode(nowCode);
        }else{
            //否则认为是当前父code的第一个子code
            return parentCode + "A"+ getNextStrNum(0);
        }
    }


    /**
     * 将数字前面位数补零
     *
     * @param num 待补零的数字
     * @return 补零完的字符串
     */
    private static String getStrNum(int num) {
        return String.format("%0" + numLength + "d", num);
    }

    /**
     * 将数字前面位数补零
     *
     * @param num 待自增后补零的数字
     * @return 自增完，补零完的字符串
     */
    private static String getNextStrNum(int num) {
        //++num 先自增 后使用 即使用自增后的结果去获取《补零字符串》
        return getStrNum(++num);
    }

    /**
     * 递增获取下个字母
     *
     * @param letter 当前字母
     * @return 下一个字母
     */
    private static char getNextLetter(char letter) {
        if (letter == 'Z') {
            return 'A';
        }
        letter++;
        return letter;
    }

    /**
     * 根据数字长度获取能表示的最大值
     * @return 该长度能表示的最大十进制数
     */
    private static int getMaxNum(){
        if(numLength ==0){
            return 0;
        }
        StringBuilder max_num = new StringBuilder();
        for (int i = 0; i< numLength; i++){
            max_num.append("9");
        }
        return Integer.parseInt(max_num.toString());
    }

}
